﻿/*
<File>
	<Copyright>Copyright © 2007, Daniel Vaughan. All rights reserved.</Copyright>
	<License see="//License.txt"/>
	<Owner Name="Daniel Vaughan" Email="danielvaughan@outcoder.com"/>
	<CreationDate>2007/11/19 20:00</CreationDate>
	<LastSubmissionDate>$Date: $</LastSubmissionDate>
	<Version>$Revision: $</Version>
</File>
*/

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Web.Security;

namespace DanielVaughan.Logging.Filters
{
	/// <summary>
	/// Restricts logging based on whether
	/// the current user belongs to a specified role group.
	/// </summary>
	class RoleMembershipFilter : HttpRequestFilterBase
	{
		readonly List<string> allowedRoles = new List<string>();

		public IEnumerable<string> AllowedRoles
		{
			get
			{
				return allowedRoles;
			}
		}

		public RoleMembershipFilter()
		{
			Init += RoleMembershipFilter_Init;
		}

		void RoleMembershipFilter_Init(object sender, FilterInitEventArgs e)
		{
			ArgumentValidator.AssertNotNull(e, "e");
			ArgumentValidator.AssertNotNull(e.ConfigurationElement, "e.ConfigurationElement");

			/* Reset state. */
			allowedRoles.Clear();

			/* TODO: put in util.*/
			var allowedRolesAttribute = e.ConfigurationElement.Attributes["Roles"];
			if (allowedRolesAttribute == null)
			{
				throw new ClientLoggingException("Roles attribute does not exists."); /* TODO: Make localizable resource. */
			}
			try
			{
				string allowedRolesValue = allowedRolesAttribute.Value;
				var machineValues = allowedRolesValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				allowedRoles.AddRange(machineValues);
			}
			catch (Exception ex)
			{
				throw new ClientLoggingException("Users attribute is invalid. Should be a comma seperated list of names.", ex); /* TODO: Make localizable resource. */
			}

			if (Action == FilterAction.Default)
			{
				Action = FilterAction.Allow;
			}
			
			if (Action != FilterAction.Allow && Action != FilterAction.Deny)
			{
				throw new ConfigurationErrorsException(InvalidActionMessage);
			}
		}

		public override bool IsValid(LogEntryOrigin origin, IClientInfo info)
		{
			if (origin != LogEntryOrigin.Remote)
			{
				return true;
			}

			if (HttpRequest == null)
			{
				return true;
			}

			string[] roles;

			try
			{
				roles = Roles.GetRolesForUser();
			}
			catch (Exception ex)
			{
				if (InternalLog.ErrorEnabled)
				{
					InternalLog.Error(string.Format("Unable to get membership roles for current user.", ex));
				}
				return false;
			}

			foreach (string role in roles)
			{
				if (allowedRoles.Contains(role))
				{
					if (Action == FilterAction.Deny)
					{
						return false;
					}

					if (Action == FilterAction.Allow)
					{
						return true;
					}
				}
			}

			return Action != FilterAction.Allow;
		}
	}
}
